昨天介紹了 OrderCreate,今天會把另外兩個都介紹完!
OrderNo
: 根據訂單編號 (必要參數)PayType
: 根據收款方式OrderDateTimeS
: 交易日期(起)OrderDateTimeE
: 交易日期(迄)PayDateTimeS
: 付款日期(起)PayDateTimeE
: 付款日期(迄)PayFlag
: 付款狀態訂單編號
、收款方式
、交易起迄
或是付款狀態
,其中一種!300
筆,所以範圍不要設太大~例如我們想要查詢:信用卡付款 + 付款完成的訂單就可以這樣下
{
"ShopNo": shop_no,
"PayType": "C",
"PayFlag": "Y"
}
收到的回應,會像是下面這樣~
訊息的意思可以參考 Spec,內容有點多
{
"ShopNo":"NA0249_001",
"Date":"202109162125",
"Status":"S",
"Description":"S0000 – 處理成功",
"OrderList":[
{
"OrderNo":"A202109150006",
"TSNo":"NA024900000158",
"TSDate":"202109151927",
"ApprovedDate":"202109151927",
"PayDate":"202109151927",
"Amount":51000,
"PayType":"C",
"PayStatus":"1C400",
"ExpireDate":"202109151938",
"RefundFlag":"N",
"RefundStatus":"",
"RefundDate":"",
"PrdtName":"OrderCreate_CreditCard_Example",
"CardParam":{
"CardPayURL":"https://sandbox.sinopac.com/QPay.WebPaySite/Bridge/PayCard?TD=NA024900000158&TK=38e938a1-bb5f-49b5-b173-b402088bb279",
"LeftCCNo":"499937",
"RightCCNo":"3145",
"AuthCode":"F56172",
"CCExpDate":"",
"CCToken":""
},
"RefundAmount":0
}
]
}
OrderQuery 大概就是這樣,讓我們繼續下一個
ShopNO
PayToken
: 訊息 TokenPayToken
會在使用者付款時,傳送給 ReturnURL
於是我寫了一個小小的程式去接收訊息,並把拿到的 Token 顯示出來
回傳訊息如下,可以看到訂單是否處理或是付款有沒有成功~
訊息的意思一樣參考 Spec,內容有點多
{
"ShopNo":"NA0249_001",
"PayToken":"1fda3bb101e044840486e8f3489ecea923ac51aacf55fef27a080170c193e025",
"Date":"202109162140",
"Status":"S",
"Description":"S0000 – 處理成功",
"TSResultContent":{
"APType":"PayOut",
"TSNo":"NA024900000167",
"OrderNo":"A202109160001",
"ShopNo":"NA0249_001",
"PayType":"C",
"Amount":"51000",
"Status":"S",
"Description":"",
"LeftCCNo":"",
"RightCCNo":"",
"CCExpDate":"",
"CCToken":"",
"PayDate":"202109162137"
}
}
今天大概就說這樣,然後明天要講什麼還不確定!
from __future__ import unicode_literals
import requests
import hashlib
import codecs
import json
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
shop_no = 'NA0249_001'
sinopac_hash = {
'a1': '',
'a2': '',
'b1': '',
'b2': ''
}
nonce_url = 'https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Nonce'
order_url = 'https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Order'
def getNonce():
nonce_data = {
'ShopNo': shop_no
}
r = requests.post(nonce_url, json=nonce_data)
return json.loads(r.content)['Nonce']
def calcHashID():
a1 = sinopac_hash['a1']
a2 = sinopac_hash['a2']
b1 = sinopac_hash['b1']
b2 = sinopac_hash['b2']
xor1 = hex(int(a1, base=16)^int(a2, base=16))
xor2 = hex(int(b1, base=16)^int(b2, base=16))
hash_id = xor1[2:]+xor2[2:]
return hash_id.upper()
def calcIV(nonce):
s = hashlib.sha256()
s.update(nonce.encode('utf-8'))
h = s.hexdigest()
return h[-16:].upper()
def calcSign(msg_content, nonce, hash_id):
sign_msg = msg_content+nonce+hash_id
s = hashlib.sha256()
s.update(sign_msg.encode('utf-8'))
h = s.hexdigest()
return h.upper()
def parseQueryData(msg_param):
if type(msg_param) != dict:
return
order_message = dict(sorted(msg_param.items(), key = lambda x: x[0]))
message = ''
for k, v in order_message.items():
if type(v) == dict or v == '':
continue
message += f"{k}={v}&"
return message[:-1]
def CBCEncrypt(key, iv, data):
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
return (cipher.encrypt(pad(data.encode('utf-8'), AES.block_size)))
def CBCDecrypt(key, iv, data):
data = codecs.decode(data, "hex")
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
return unpad(cipher.decrypt(data), AES.block_size)
def apiService(service, sign, nonce, msg):
api_data = {
'Version': '1.0.0',
'ShopNo': shop_no,
'APIService': service,
'Sign': sign,
'Nonce': nonce,
'Message': msg
}
r = requests.post(order_url, json = api_data)
resp = json.loads(r.content)
return (resp['Sign'], resp['Nonce'], resp['Message'])
## 這邊修改成每個 API 都共用
def queryAPI(api, api_msg):
nonce = getNonce()
hash_id = calcHashID()
iv = calcIV(nonce)
content = parseQueryData(api_msg)
signature = calcSign(content, nonce, hash_id)
msg = json.dumps(api_msg, ensure_ascii=False).replace(' ','')
enc_message = CBCEncrypt(hash_id, iv, msg).hex().upper()
if api == "C":
resp_sign, resp_nonce, resp_message = apiService('OrderCreate', signature, nonce, enc_message)
elif api == "Q":
resp_sign, resp_nonce, resp_message = apiService('OrderQuery', signature, nonce, enc_message)
elif api == "PQ":
resp_sign, resp_nonce, resp_message = apiService('OrderPayQuery', signature, nonce, enc_message)
else:
return
resp_iv = calcIV(resp_nonce)
dec_msg = CBCDecrypt(hash_id, resp_iv, resp_message)
return json.loads(dec_msg)
order_create = {
"ShopNo": shop_no,
"OrderNo": "A202109160003",
"Amount": 51000,
"CurrencyID": "TWD",
"PayType": "C",
"CardParam": {
"AutoBilling": "Y"
},
"PrdtName": "OrderCreate_CreditCard_Example",
"ReturnURL": "<your_return_url>",
"BackendURL": "<your_backend_url>"
}
order_query = {
"ShopNo": shop_no,
"PayType": "C",
"PayFlag": "Y"
}
order_pay_query = {
"ShopNo": shop_no,
"PayToken": "1fda3bb101e044840486e8f3489ecea923ac51aacf55fef27a080170c193e025"
}
print(queryAPI("C", order_create))
print(queryAPI("Q", order_query))
print(queryAPI("PQ", order_pay_query))